package org.hyson.gofun;
import android.graphics.Point;
import java.io.Serializable;
public class Board  implements Serializable{
        //棋盘尺寸
        private int width;
        private int height;
        private Pieces pieces[][];
        private Point  cur_point;

        public Board(int width, int height){
                if(width < 4 || height < 4){
                        this.width = 4;
                        this.height = 4;
                }else{
                        this.width = width;
                        this.height = height;
                }
                pieces= new Pieces[width][height];
                for(int i = 0; i < this.width; i++)
                        for(int j = 0; j < this.height; j++)
                                pieces[i][j] = Pieces.EMPTY;
                cur_point = new Point();
                cur_point.x = -1;
                cur_point.y = -1;
        }
        public void setCurPoint(Point pos){
        	cur_point.x = pos.x;
        	cur_point.y = pos.y;
        }
        public Point getCurPoint(){
        	return cur_point;
        }
        private boolean valid_pos(Point pos){
                if(pos.x < 0 || pos.y < 0 || pos.x >= width || pos.y >= height)
                        return false;

                return true;
        }
        private boolean emptyPos(int x, int y){
                Point pos = new Point();
                pos.x = x;
                pos.y = y;
                return emptyPos(pos);
        }
        private boolean emptyPos(Point pos){
                if(!valid_pos(pos))
                        return false;
                return (getPos(pos) == Pieces.EMPTY);
        }
        public boolean getFreePos(Point pos){
        	 for(int i = 0; i < this.width; i++){
                 for(int j = 0; j < this.height; j++){
                      if(emptyPos(i, j)){
                    	  pos.x = i;
                    	  pos.y = j;
                    	  return true;
                      }
                 }
                 
        	 }
        	 return false;
        }
        public Pieces getPos(int x, int y){
                if(x >= width || y >= height)
                        return Pieces.NO;
                return pieces[x][y];
        }
        public Pieces getPos(Point pos){
                if(!valid_pos(pos))
                        return Pieces.NO;

                return pieces[pos.x][pos.y];
        }
        public boolean setPos(int x, int y, Pieces p){
                Point pos = new Point();
                pos.x = x;
                pos.y = y; 
                return setPos(pos, p);
        }
        public  boolean  setPos(Point pos, Pieces p){
                if(!valid_pos(pos))
                        return false;
                pieces[pos.x][pos.y] = p;
                return true;
        }
        public boolean setPieces(Point pos, Pieces p){
                if(!emptyPos(pos))
                        return false;
                if(!setPos(pos, p))
                        return false;
                return true;
        }
        private boolean canMove(Point src_pos, Point dst_pos){
                if(src_pos.y > 0){
                        if(src_pos.y -1 == dst_pos.y && src_pos.x == dst_pos.x){
                                return true;
                        }
                }
                if(src_pos.x > 0){
                        if(src_pos.x -1 == dst_pos.x && src_pos.y == dst_pos.y){
                                return true;
                        }
                }
                if(src_pos.y < height -1){
                        if(src_pos.y + 1 == dst_pos.y && src_pos.x == dst_pos.x){
                                return true;
                        }
                }
                if(src_pos.x < height -1){
                        if(src_pos.x + 1 == dst_pos.x && src_pos.y == dst_pos.y){
                                return true;
                        }
                }
                return false;
        }
        public  boolean movePieces(Point src_pos, Point dst_pos, Pieces who){
                if(getPos(src_pos) != who)
                        return false;
                if(!emptyPos(dst_pos))
                        return false;
                if(!canMove(src_pos, dst_pos)){
			return false;
                }
                setPos(src_pos, Pieces.EMPTY);
                setPos(dst_pos, who);
                return true;
        }
        public boolean getPlayerPos(Point src_pos, Pieces player){
        	 for(int i = 0; i < this.width; i++){
                 for(int j = 0; j < this.height; j++){
                      if(getPos(i, j) == player){
                    	  src_pos.x = i;
                    	  src_pos.y = j;
                    	  return true;
                      }
                 }
        	 }
             return false;
        }
        public int getKills(int x, int y, Pieces cur_player){
                Point pos = new Point();
                pos.x = x;
                pos.y = y;
                return getKills(pos, cur_player);
        }
        public int getKills(Point src_pos, Pieces cur_player){
                //check lines
                boolean find_kills = true;
                for(int i = 0; i < width; i++){
                        if(getPos(i,src_pos.y) != cur_player){
                                find_kills = false;
                                break;
                        }
                }
                if(find_kills){
                        return 2;
                }
                find_kills = true;
                //check column 
                for(int i = 0; i < height; i++){
                        if(getPos(src_pos.x, i) != cur_player){
                                find_kills = false;
                                break;
                        }
                }
                if(find_kills){
                        return 2;
                }
                //check square
                if(src_pos.x > 0 && src_pos.y > 0){
                        if(getPos(src_pos.x, src_pos.y -1) == cur_player&&
                                getPos(src_pos.x -1, src_pos.y) == cur_player&&
                                getPos(src_pos.x -1, src_pos.y -1) == cur_player){

                                return 1;
                        }

                }
                if(src_pos.x > 0 && src_pos.y < height - 1){
                        if(getPos(src_pos.x -1, src_pos.y) == cur_player&&
                                getPos(src_pos.x , src_pos.y + 1) == cur_player&&
                                getPos(src_pos.x - 1, src_pos.y +1) == cur_player){

                                return 1;
                        }
                }
                if(src_pos.x < width -1 && src_pos.y > 0){
                        if(getPos(src_pos.x , src_pos.y -1) == cur_player&&
                                getPos(src_pos.x + 1 , src_pos.y) == cur_player&&
                                getPos(src_pos.x + 1, src_pos.y -1) == cur_player){

                                return 1;
                        }
                }
                if(src_pos.x < width -1 && src_pos.y < height - 1){
                        if(getPos(src_pos.x + 1 , src_pos.y) == cur_player&&
                                getPos(src_pos.x  , src_pos.y + 1) == cur_player&&
                                getPos(src_pos.x +1, src_pos.y +1) == cur_player){
                                return 1;
                        }
                }
                return 0;
        }
        public boolean killPieces(Point pos, GameStatus status){
                if(status == GameStatus.GAME_SET || status == GameStatus.GAME_SET_LAST)
                    setPos(pos, Pieces.FORBID);
                else
                    setPos(pos, Pieces.EMPTY);

                return true;
        }
        public Pieces noPieces(){
	         int player1_num = 0;
	         int player2_num = 0;
	         for(int i = 0; i < this.width; i++){
                        for(int j = 0; j < this.height; j++){
                                if(pieces[i][j] == Pieces.P1){
                                		player1_num++;
                                }else if(pieces[i][j] == Pieces.P2){
                                	player2_num++;
                                }
						}
			}
        
		if(player1_num <= 3){
			return Pieces.P1;
		}
		if(player2_num <= 3){
			return Pieces.P2;
		}
        	return Pieces.NO;
        }
        public int haveMoves(int x, int y){
                Point pos = new Point();
                pos.x = x;
                pos.y = y;
                return haveMoves(pos);
        }
        public int haveMoves(Point src_pos){
        		int ret = 0;
                if(src_pos.y > 0){
                        if(emptyPos(src_pos.x, src_pos.y - 1))
                                ret |= 0x1;
                }
                if(src_pos.x > 0){
                        if(emptyPos(src_pos.x - 1, src_pos.y))
                                ret |= 0x02;
                }
                if(src_pos.y < height -1){
                        if(emptyPos(src_pos.x , src_pos.y + 1))
                                ret |= 0x04;
                }
                if(src_pos.x < height -1){
                        if(emptyPos(src_pos.x + 1 , src_pos.y))
                                ret |= 0x08;
                }
                return ret;
        }
        public boolean noMoves(Pieces cur_player){
                boolean find_kills = true;
                for(int i = 0; i < this.width; i++){
                        for(int j = 0; j < this.height; j++){
                                if(pieces[i][j] == cur_player)
                                        if(haveMoves(i, j) !=0){
                                                find_kills = false;
                                                break;
                                        }
                                }
                }
                return find_kills;
        }
        public boolean getFreeMoves(Point src_pos, Point dst_pos, Pieces cur_player){
            boolean find_kills = false;
            int ret = 0;
            for(int i = 0; i < this.width; i++){
                    for(int j = 0; j < this.height; j++){
                            if(pieces[i][j] == cur_player)
                                    if((ret = haveMoves(i, j)) != 0){
                                    		src_pos.x = i;
                                    		src_pos.y = j;
                                    		
                                            	find_kills = true;
                                    		if((ret & 0x01 )!= 0){
                                    			dst_pos.x = src_pos.x;
                                    			dst_pos.y = src_pos.y -1;
							break;
                                    		
                                    		}
                                    		if((ret & 0x02 )!= 0){
                                        		dst_pos.x = src_pos.x - 1;
                                        		dst_pos.y = src_pos.y;
							break;
                                    		}
                                    		if((ret & 0x04 )!= 0){
                                        		dst_pos.x = src_pos.x;
                                        		dst_pos.y = src_pos.y + 1;
							break;
                                    		}
                                    		if((ret & 0x08 )!= 0){
                                        		dst_pos.x = src_pos.x + 1;
                                        		dst_pos.y = src_pos.y;
							break;
                                    		}
                                            	break;
                                    }
                            }
            }
            return find_kills;
        }
        public void cleanForbid(){
                for(int i = 0; i < this.width; i++){
                        for(int j = 0; j < this.height; j++){
                                if(pieces[i][j] == Pieces.FORBID)
                                        pieces[i][j] = Pieces.EMPTY;
                                }
                }
        }
        public void draw(){
                for(int i = 0; i < this.width; i++){
                        for(int j = 0; j < this.height; j++){
                                if(emptyPos(i, j))
                                        System.out.print("( " + i + " " + j + " *) ");
                                if(pieces[i][j] == Pieces.P1)
                                        System.out.print("( " + i + " " + j + " @) ");
                                if(pieces[i][j] == Pieces.P2)
                                        System.out.print("( " + i + " " + j + " #) ");
                                if(pieces[i][j] == Pieces.FORBID)
                                        System.out.print("( " + i + " " + j + " $) ");
                        }
                        System.out.println("");
                        System.out.println("");
                }
        } 
        public boolean getAlmostKill(Pieces who, Point pos){
                boolean find = false;
                for(int i = 0; i < this.width; i++){
                        for(int j = 0; j < this.height; j++){
                                if(emptyPos(i, j)){
                                        setPos(i, j, who);
                                        if(getKills(i, j, who) > 0){
                                                pos.x = i;
                                                pos.y = j;
                                                setPos(i, j, Pieces.EMPTY);
                                                return true;
                                        }
                                        setPos(i, j, getRival(who));
                                        if(getKills(i, j, getRival(who)) > 0){
                                                pos.x = i;
                                                pos.y = j;
                                                find = true;
                                        }
                                        setPos(i, j, Pieces.EMPTY);
                                }
                        }
                }
                return find;
        }
        public boolean getKillSetPos(Pieces who, Point pos){
                boolean find = false;
                for(int i = 0; i < this.width; i++){
                        for(int j = 0; j < this.height; j++){
                                if(emptyPos(i, j)){
                                        if(getKills(i, j, who) > 0){
                                                find = true;
                                                pos.x = i;
                                                pos.y = j;
                                                return true;
                                        }
                                        if(getKills(i, j, getRival(who)) > 0){
                                                pos.x = i;
                                                pos.y = j;
                                                find = true;
                                        }
                                }
                        }
                }
                return find;

        }
        public Pieces getRival(Pieces who){

                if(who == Pieces.P1)
                        return Pieces.P2;
                if(who == Pieces.P2)
                        return Pieces.P1;

                return Pieces.NO;
        }
}
